#include "UserDao.h"

#include <QtSql/QSqlQuery>
#include <QtSql/QSqlError>
#include <QDateTime>
#include <QDebug>


UserDao::UserDao(QSqlDatabase& db) : db_(db) {}

std::optional<UserData> UserDao::findByUsername(QSqlDatabase& db, const QString& username)
{
    QSqlQuery query(db);
    try
    {
        query.prepare("SELECT ID,ACCOUNT,PASSWORD,NAME,USER_STATUS,LAST_LOGIN_TIME FROM sys_user WHERE ACCOUNT = :username");
        query.bindValue(":username", username); //通过自定义的别名来替代
        if (!query.exec() || !query.first())
        {
            return std::nullopt;
        }
        UserData user;
        user.id = query.value("ID").toString();
        user.account = query.value("ACCOUNT").toString();
        user.password = query.value("PASSWORD").toString();
        user.name = query.value("NAME").toString();
        user.userStatus = query.value("USER_STATUS").toString();
        user.lastLoginTime = query.value("LAST_LOGIN_TIME").toDateTime();
        return user;
    }
    catch (const QSqlError::ErrorType& e)
    {
        qCritical() << "[DAO] Query failed:" << query.lastError().text();
        qCritical() << "[DAO] Query error:" << e;
        return std::nullopt;
    }
}

std::optional<SysUser> UserDao::getUserById(QSqlDatabase& db, const QString& userId)
{
    QSqlQuery query(db);
    SysUser user;
    try
    {
        query.prepare(
                 "SELECT u.ID, u.AVATAR, u.SIGNATURE, u.ACCOUNT, u.NAME, u.NICKNAME, u.GENDER, "
                 "u.AGE, u.BIRTHDAY, u.EMAIL, u.PHONE, "
                 "o.NAME AS ORG_NAME, p.NAME AS POSITION_NAME "
                 "FROM sys_user u "
                 "LEFT JOIN sys_org o ON u.ORG_ID = o.ID "
                 "LEFT JOIN sys_position p ON u.POSITION_ID = p.ID "
                 "WHERE u.ID = :userId"
             );
        query.bindValue(":userId", userId);
        if (query.exec() && query.next())
        {
            user.id = query.value("ID").toString();
            user.avatar = query.value("AVATAR").toString();
            user.signature = query.value("SIGNATURE").toString();
            user.account = query.value("ACCOUNT").toString();
            user.name = query.value("NAME").toString();
            user.nickname = query.value("NICKNAME").toString();
            user.gender = query.value("GENDER").toString();
            user.age = query.value("AGE").toInt();
            user.birthday = query.value("BIRTHDAY").toDate();
            user.email = query.value("EMAIL").toString();
            user.phone = query.value("PHONE").toString();
            user.orgName = query.value("ORG_NAME").toString();
            user.positionName = query.value("POSITION_NAME").toString();
        }
    }
    catch (const QSqlError::ErrorType& e)
    {
        qCritical() << "[DAO] Query error:" << e;
    }
    return user;
}

bool UserDao::updateLoginInfo(QSqlDatabase& db, QString userId, const QString& ip, const QString& address, const QString& device)
{
    QSqlQuery query(db);
    try
    {
        query.prepare(
                 "UPDATE users SET "
                 "LAST_LOGIN_IP = LATEST_LOGIN_IP, "
                 "LAST_LOGIN_ADDRESS = LATEST_LOGIN_ADDRESS, "
                 "LAST_LOGIN_TIME = LATEST_LOGIN_TIME, "
                 "LAST_LOGIN_DEVICE = LATEST_LOGIN_DEVICE, "
                 "LATEST_LOGIN_IP = :ip, "
                 "LATEST_LOGIN_ADDRESS = :address, "
                 "LATEST_LOGIN_TIME = CURRENT_TIMESTAMP, "
                 "LATEST_LOGIN_DEVICE = :device "
                 "WHERE ID = :userId"
             );
        query.bindValue(":ip", ip);
        query.bindValue(":address", address);
        query.bindValue(":device", device);
        query.bindValue(":userId", userId);
        query.exec();
        return true;
    }
    catch (const std::exception& e)
    {
        qCritical() << "[DAO] Update failed:" << e.what();
        return false;
    }
}

bool UserDao::updateLoginTime(QSqlDatabase& db, const QString& username)
{
    QSqlQuery query(db);
    try
    {
        const QDateTime now = QDateTime::currentDateTime();
        query.prepare("UPDATE sys_user SET LAST_LOGIN_TIME =:now WHERE ACCOUNT = :username");
        query.bindValue(":now", now);
        query.bindValue(":username", username);
        query.exec();
        return true;
    }
    catch (const std::exception& e)
    {
        qCritical() << "[DAO] Update failed:" << e.what();
        return false;
    }
}
